<?php
/**
 * @package mikrokosmos
 * file created on 11/mag/08
 *
 * jaco_at_pixeldump_dot_org
 */

// constants in namespace entry
define("CONSTANT_Namespace", 			8); // 0x08
define("CONSTANT_PackageNamespace",    22); // 0x16
define("CONSTANT_PacakgeInternalNs",   23); // 0x17
define("CONSTANT_ProtectedNamespace",  24); // 0x18
define("CONSTANT_ExplicitNamespace",   25); // 0x19
define("CONSTANT_StaticProtectedNs",   26); // 0x1A
define("CONSTANT_PrivateNs", 			5); // 0x05


// Multiname kind
define("CONSTANT_QName",		7);	// 0x07
define("CONSTANT_QNameA",      13);	// 0x0D
define("CONSTANT_RTQName",     15);	// 0x0F
define("CONSTANT_RTQNameA",    16);	// 0x10
define("CONSTANT_RTQNameL",    17);	// 0x11
define("CONSTANT_RTQNameLA",   18);	// 0x12
define("CONSTANT_Multiname",    9);	// 0x09
define("CONSTANT_MultinameA",  14);	// 0x0E
define("CONSTANT_MultinameL",  27);	// 0x1B
define("CONSTANT_MultinameLA", 28);	// 0x1C


// methodInfo flags
define("NEED_ARGUMENTS",    1);	// 0x01
define("NEED_ACTIVATION",   2);	// 0x02
define("NEED_REST", 	    4);	// 0x04
define("HAS_OPTIONAL", 	    8);	// 0x08
define("SET_DXNS", 		   64);	// 0x40
define("HAS_PARAM_NAMES", 128);	// 0x80

// methodInfo optional parameter kind
define("CONSTANT_Int",				   3);	// 0x03  integer
define("CONSTANT_UInt",				   4);	// 0x04  uinteger
define("CONSTANT_Double",			   6);	// 0x06  double
define("CONSTANT_Utf8",				   1);	// 0x01  string
define("CONSTANT_True",			      11);	// 0x0B  -
define("CONSTANT_False",		      10);	// 0x0A  -
define("CONSTANT_Null",			      12);	// 0x0C  -
define("CONSTANT_Undefined",		   0);	// 0x00  -
//define("CONSTANT_Namespace",		   8);	// 0x08  namespace
//define("CONSTANT_PackageNamespace",	  24);	// 0x16  namespace
//define("CONSTANT_PackageInternalNs",  23);	// 0x17  Namespace
//define("CONSTANT_ProtectedNamespace", 24);	// 0x18  Namespace
//define("CONSTANT_ExplicitNamespace",  25);	// 0x19  Namespace
//define("CONSTANT_StaticProtectedNs",  26);	// 0x1A  Namespace
//define("CONSTANT_PrivateNs",		   5);	// 0x05 namespace

// instanceInfo flags
define("CONSTANT_ClassSealed",	    1);	// 0x01
define("CONSTANT_ClassFinal",	    2);	// 0x02
define("CONSTANT_ClassInterface",	4);	// 0x04
define("CONSTANT_ClassProtectedNs", 8);	// 0x08

// TRAIT type
define("TRAIT_Slot",     0);
define("TRAIT_Method",   1);
define("TRAIT_Getter",   2);
define("TRAIT_Setter",   3);
define("TRAIT_Class",    4);
define("TRAIT_Function", 5);
define("TRAIT_Const",    6);

// trait attributes
define("ATTR_Final",    1); // 0x1
define("ATTR_Override", 2); // 0x2
define("ATTR_Metadata", 4); // 0x4


if(!class_exists("MKTagHeader")){ class MKTagHeader {}}


/**
 * flex2 Product Info
 */
class MKProductInfo extends MKTagHeader {

	var $tagData = "";
							// 			examples
	var $product;			// UI32	??	Macromedia Flex for J2EE
	var $edition;			// UI32	??	Developer Edition
	var $version;			// UI16		2.0
	var $build;				// UI64	??	155542
	var $compileDate;		// UI54		03/05/07 19.55

	// the constructor
	function MKProductInfo($tagData = "", $pid = array()){

		$this->tagData = $tagData;
		$this->get_productInfo_data($pid);
	}

	function set_productInfo_data($pid = array()){

		if(count($pid))	$this->get_productInfo_data($pid);
		else $pid = $this->fetch_assoc();

		$this->tagData = write_productInfo_data($pid);

		return $this->tagData;
	}

	function get_productInfo_data($pid = array()){

		if(!count($pid)) $cnc = read_productInfo_data($this->tagData);

		//$this->classNames = $cnc["classNames"];
		//$this->objIDs = $cnc["objIDs"];
	}

	//
	function fetch_assoc(){
		$pid = array();

		return $pid;
	}

	//
	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "productInfo"){

		$phStr = "";
		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName ." ";
		$xmlStr .= "product=\"" .$phStr ."\" ";
		$xmlStr .= "edition=\"" .$phStr ."\" ";
		$xmlStr .= "version=\"" .$phStr ."\" ";
		$xmlStr .= "build=\"" .$phStr ."\" ";
		$xmlStr .= "compileDate=\"" .$phStr ."\" >";

		$pfx = get_xml_indent_row(++$tabLevel);
		$xmlStr .= $pfx ."<hexData>";
		$xmlStr .= hex_dump($this->tagData, true);
		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx ."</hexData>";

		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx ."</" .$nodeName .">";

		return $xmlStr;
	}

	function update_tagData(){
		return $this->set_productInfo_data();
	}

}

/**
 * f9 class names tag
 */
class MKClassNames extends MKTagHeader{

	var $tagData = "";
	var $objIDs = array();
	var $classNames = array();

	function MKClassNames($tagData = "", $classNames = array(), $objIDs = array()){

		$this->tagData = $tagData;

		if(strlen($tagData)) $this->get_classNameContainer_data();
		else {
			$this->classNames = $classNames;
			$this->objIDs = $objIDs;
		}
	}

	//
	function set_classNames($classNames = array()){
		$this->classNames = $classNames;
	}
	function get_classNames(){ return $this->classNames; }

	//
	function set_objIDs($objIDs = array()){ $this->objIDs = $objIDs; }
	function get_objIDs(){ return $this->objIDs; }

	function add_class_definition($className = "", $objID = 1){
		if(strlen($className)){
			$this->classNames[] = $className;

			// ensure to assign unique classID
			$cid = $objID;

			while(in_array($cid, $this->objIDs ,true)) $cid++;

			$this->objIDs[] = $cid;
		}
	}

	function get_class_definitionAt($idx){

		$idx = max(count($this->classNames) - 1, $idx);

		$classDef = array();
		$classDef["id"] = $this->classIDs[$idx];
		$classDef["name"] = $this->classNames[$idx];
	}

	function set_classNameContainer_data($cnc = array()){

		if(count($cnc))	$this->get_classNameContainer_data($cnc);
		else $cnc = $this->fetch_assoc();

		$this->tagData = write_classNameContainer_data($cnc);

		return $this->tagData;
	}

	function get_classNameContainer_data($cnc = array()){

		if(!count($cnc)) $cnc = read_classNameContainer_data($this->tagData);

		$this->classNames = $cnc["classNames"];
		$this->objIDs = $cnc["objIDs"];
	}

	//
	function fetch_assoc(){
		$cnc = array();
		$cnc["classNames"] = $this->classNames;
		$cnc["objIDs"] = $this->objIDs;

		return $cnc;
	}

	//
	//
	function fetch_xml($includeHeader = true, $tabLevel = 0){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$cCount = count($this->classNames);

		$xmlStr .= $pfx ."<classNames count=\"";
		$xmlStr .= $cCount ."\">";

		$pfx = get_xml_indent_row(++$tabLevel);

		for($i = 0; $i < $cCount; $i++){
			$xmlStr .= $pfx ."<class objID=\"";
			$xmlStr .= $this->objIDs[$i] ."\" ";
			$xmlStr .= "name=\"";
			$xmlStr .= $this->classNames[$i] ."\" />";
		}

		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx . "</classNames>";

		return $xmlStr;
	}

	function update_tagData(){
		return $this->set_classNameContainer_data();
	}
}


/**
 * 0x52 swf9 tag code DoABC2
 * NOTICE: this is a very basic support
 * commented vars are managed by class, simply use count() and fit +/-1 when needed
 */
class MKAbcContainer extends MKTagHeader {

	var $tagData = "";
	//var $magic = "";				//

	// no itemID provided

	var $flags = 1;					// uint32 kDoAbcLazyInitializeFlag enabled
	var $abcName = "";				// swfstring, default is null
	var $minorVersion = 16;			// U16, always 16, future changes ensure backward compatibility
	var $majorVersion = 46;			// U16, always 46 future changes will broke abc format

	//var $cIntPoolcount;			// U30 constant_int_pool_count
	var $cInt = array();			// ConstantInteger[constant_int_pool_count]
									// Cpool entries for integers

 	//var $cUintPoolCount;			// U30 constant_uint_pool_count
	var $cUInt = array();			// ConstantUInteger[constant_uint_pool_count]
									// Cpool entries for uints

	//var $cDoublePoolCount;		// U30 constant_double_pool_count
	var $cDouble = array();			// ConstantDouble[constant_double_pool_count]
									// Cpool entries for doubles

	//var $cStringPoolCount;		// U30 constant_string_pool_count
	var $cString = array();			// ConstantString[constant_string_pool_count]
									// Cpool entries for strings

	//var $cNamespacePoolCount;		// U30 constant_namespace_pool_count
	var $cNamespace = array();		// ConstantNamespace[constant_namespace_pool_count]
									// Cpool entries for namespaces

	//var $cnSetPoolCount;			// U30 constant_namespace_set_pool_count
	var $cNamespaceSet = array();	// ConstantNamespaceSet[constant_namespace_set_pool_count]
									// Cpool entries for namespace sets

	//var $cMultinamePoolCount;		// U30 constant_multiname_pool_count
	var $cMultiname = array();		// ConstantMultiname[constant_multiname_pool_count]
									// Cpool entries for Multinames, Qnames, RTQnames, and RTQnamesLate

	//var $methodsCount;			// U30 methods_count
	var $methodInfo = array();		// MethodInfo[methods_count]

	//var $metadataCount;			// U30 metadata_count
	var $metadataInfo = array();	// MetadataInfo[metadata_count]

	//var $classCount;				// U30 class_count
	var $instanceInfo = array();	// InstanceInfo[class_count]
	var $classInfo = array();		// ClassInfo[class_count]

	//var $scriptCount;				// U30 script_count
	var $scriptInfo = array();		// ScriptInfo[script_count]
									// ScriptInfo[script_count-1] is main entry point

	//var $bodiesCount;				// U30 bodies_count
	var $methodBodyInfo = array();		// MethodBody[bodies_count]


	// the constructor
	function MKAbcContainer($tagData = "", $abcName = ""){
		$this->tagID = 0x52;
		$this->abcName = $abcName;
		$this->tagData = $tagData;
	}


	//
	function add_constantInt($ci) {
		$this->cInt[] = $ci;
	}

	//
	function add_constantUint($cui) {
		$this->cUint[] = $cui;
	}

	//
	function add_constantDouble($cdbl) {
		$this->cDouble[] = $cdbl;
	}

	// constantString entry is a simple string
	// when compiled it's: u30 size, string string (not 0 terminated)
	function add_constantString($cs) {
		$this->cString[] = $cs;
	}

	// constantNamespace entry is a simple indexed array:
	// u8 kind, u30 name_index
	function add_constantNamespace($cns) {
		$this->cNamespace[] = $cns;
	}

	//
	function add_constantNamespaceSet($cnss) {
		$this->cNamespaceSet[] = $cnss;
	}

	// constantMultiname entry is an indexed array composed by:
	// u8 kind
	// u8 data[]
	// data depends on kind, each item can be:
	// array -> QName, Multiname
	// u30 -> RTQName, MultinameL
	// not set -> RTQNameL
	function add_constantMultiname($cmn) {
		$this->cMultiname[] = $cmn;
	}

	//
	function add_methodInfo($mi) {
		$this->methodInfo[] = $mi;
	}

	//
	function add_metadataInfo($mi) {
		$this->metadataInfo[] = $mi;
	}

	//
	function add_instanceInfo($ii) {
		$this->instanceInfo[] = $ii;
	}

	//
	function add_classInfo($ci) {
		$this->classInfo[] = $ci;
	}

	//
	function add_scriptInfo($si) {
		$this->scriptInfo[] = $si;
	}

	//
	function add_methodBodyInfo($mb) {
		$this->methodBodyInfo[] = $mb;
	}

	//
	function set_doAbc2_data(){

		$buf = swf_dword($this->flags);
		$buf .= swf_string($this->abcName);
		$buf .= swf_word($this->minorVersion);
		$buf .= swf_word($this->majorVersion);

		// constant pools
		$ciCount = count($this->cInt);

		if($ciCount){
			$buf .= write_u30($ciCount + 1);

		}
		else $buf .= NIL;

		$cuiCount = count($this->cUInt);

		if($cuiCount) {
			$buf .= write_u30($cuiCount + 1);
		}
		else $buf .= NIL;

		$dCount = count($this->cDouble);

		if($dCount){
			$buf .= write_u30($dCount + 1);

		}
		else $buf .= NIL;

		$sCount = count($this->cString);

		if($sCount){
			$buf .= write_u30($sCount + 1);

			foreach($this->cString as $cs){
				$sLength = strlen($cs);

				if($sLength){
					$buf .= write_u30($sLength); // size
					$buf .= $cs; //
				}
				else $buf .= NIL;
			}
		}
		else $buf .= NIL;

		$nsCount = count($this->cNamespace);

		if($nsCount){
			$buf .= write_u30($nsCount + 1);

			foreach($this->cNamespace as $ns){
				$buf .= chr($ns[0]);
				$buf .= write_u30($ns[1]);
			}
		}
		else $buf .= NIL;

		$nssCount = count($this->cNamespaceSet);

		if($nssCount){
			$buf .= write_u30($nssCount + 1);


		}
		else $buf .= NIL;

		$mnCount = count($this->cMultiname);

		if($mnCount){
			$buf .= write_u30($mnCount + 1);

			foreach($this->cMultiname as $cm){
				$buf .= chr($cm[0]);

				// note: RTQNameL has no data
				if($cm[0] == CONSTANT_QName || $cm[0] == CONSTANT_QNameA){

					foreach($cm[1] as $d) $buf .= write_u30($d);

				}
				else if($cm[0] == CONSTANT_RTQName || $cm[0] == CONSTANT_RTQNameA){
					$buf .= write_u30($cm[1]);
				}
				else if($cm[0] == CONSTANT_Multiname || $cm[0] == CONSTANT_MultinameA){

					foreach($cm[1] as $d) $buf .= write_u30($d);

				}
				else if($cm[0] == CONSTANT_MultinameL){
					$buf .= write_u30($cm[1]);
				}
			}
		}
		else $buf .= NIL;


		// INFOS

		// method
		$mCount = count($this->methodInfo);
		$buf .= write_u30($mCount);

		if($mCount){
			foreach($this->methodInfo as $mi){
				$buf .= $mi->get_buf();
			}
		}

		// metadata
		$mdCount = count($this->metadataInfo);
		$buf .= write_u30($mdCount);

		if($mdCount){

		}


		// instance and class, they MUST be the same amount (classInfos are complementary to instanceInfos)
		$iCount = count($this->instanceInfo);
		$buf .= write_u30($iCount);

		if($iCount){
			foreach($this->instanceInfo as $ii) $buf .= $ii->get_buf();
			foreach($this->classInfo as $ci) $buf .= $ci->get_buf();
		}

		// script
		$sCount = count($this->scriptInfo);
		$buf .= write_u30($sCount);

		if($sCount){
			foreach($this->scriptInfo as $si) $buf .= $si->get_buf();
		}

		// method body
		$mCount = count($this->methodBodyInfo);
		$buf .= write_u30($mCount);

		if($mCount){
			foreach($this->methodBodyInfo as $mi) $buf .= $mi->get_buf();
		}


		$this->tagData = SWFTag_long_header($this->tagID, strlen($buf)) .$buf;
		return $this->tagData;
	}

	//
	function get_doAbc2_data(){

		//if(!count($dad)) $dad = read_doAbc2_data($this->tagData);
		//return $dad;
	}

	//
	function fetch_assoc() {

	}


	//
	function fetch_xml($includeHeader = true, $tabLevel = 0, $nodeName = "doABC2"){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<" .$nodeName .">";

		/* TODO: implement xml */

		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx . "</" .$nodeName .">";

		return $xmlStr;
	}


	function update_tagData() {
		return $this->set_doAbc2_data();
	}
}


/**
 * Scene name
 */
class MKSceneNames extends MKTagHeader{
	var $tagData = "";
	var $sceneNames = array();

	function MKSceneNames($tagData = "", $sceneNames = array()){

		$this->tagData = $tagData;
		if(strlen($tagData)) $this->get_sceneNameContainer_data();
		else $this->sceneNames = $sceneNames;
	}

	//
	function set_sceneNames($sceneNames = array()){
		$this->sceneNames = $sceneNames;
	}
	function get_sceneNames(){ return $this->sceneNames; }

	function add_sceneName($sceneName = ""){
		if(strlen($sceneName)) $this->sceneNames[] = $sceneName;
	}

	function get_sceneNameAt($idx){
		$idx = max(count($this->sceneNames) - 1, $idx);
		return $this->sceneNames[$idx];
	}

	function set_sceneNameContainer_data($snc = array()){

		if(count($snc))	$this->get_sceneNameContainer_data($snc);
		else $snc = $this->fetch_assoc();

		$this->tagData = write_sceneNameContainer_data($snc);

		return $this->tagData;
	}

	function get_sceneNameContainer_data($snc = array()){

		if(!count($snc)) $snc = read_sceneNameContainer_data($this->tagData);

		$this->sceneNames = $snc["sceneNames"];
	}

	//
	function fetch_assoc(){
		$snc = array();
		$snc["sceneNames"] = $this->sceneNames;

		return $snc;
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<sceneNames count=\"";
		$xmlStr .= count($this->sceneNames) ."\">";

		$pfx = get_xml_indent_row(++$tabLevel);
		foreach($this->sceneNames as $sn){
			$xmlStr .= $pfx ."<scene name=\"";
			$xmlStr .= $sn ."\" />";
		}

		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx . "</sceneNames>";

		return $xmlStr;
	}

	function update_tagData(){
		return $this->set_sceneNameContainer_data();
	}
}


class MKDebugMode extends MKTagHeader {

	var $tagData;

	function MKDebugMode($tagData = "") {

		if(strlen($tagData)) {
			$this->tagData = $tagData;
			$this->get_debugMode_data();
		}
	}

	function set_debugMode_data() {
		/* TODO */
	}

	function get_debugMode_data() {
		/* TODO */
	}

	function fetch_assoc() {
		/* TODO */
	}

	//
	function fetch_xml($includeHeader = true, $tabLevel = 0){

		$xmlStr = $includeHeader ? XML_HEADER : "";
		$pfx = get_xml_indent_row(++$tabLevel);

		$xmlStr .= $pfx ."<DebugMode length=\"";
		$xmlStr .= strlen($this->tagData) ."\">";
		$pfx = get_xml_indent_row(++$tabLevel);
		$xmlStr .= $pfx . "<hexData><![CDATA[";
		$xmlStr .= hex_dump($this->tagData, true) ."]]>";
		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx . "</hexData>";
		$pfx = get_xml_indent_row(--$tabLevel);
		$xmlStr .= $pfx . "</DebugMode>";

		return $xmlStr;
	}

}


class MethodInfoEntry {

	var $buf = 0;
	var $returnType = 0; 	// u30

	//var $pCount = 0;		// u30
	var $pTypes = array();
	var $nameIndex = 0;		// u30
	var $flags = 0;	    	// u8

	var $options;
	var $paramNames;

	function MethodInfoEntry($returnType = 0, $pTypes = array(), $nameIndex = 0, $flags = 0) {

		$this->returnType = $returnType;
		$this->pTypes = $pTypes;
		$this->nameIndex = $nameIndex;
		$this->flags = $flags;
	}

	//
	function set_returnType($returnType) { $this->returnType = $returnType; }
	function get_returnType() { return $this->returnType; }

	//
	function set_pTypes($pTypes) { $this->pTypes = $pTypes; }
	function get_pTypes() { return $this->pTypes; }

	//
	function set_nameIndex($nameIndex) { $this->nameIndex = $nameIndex; }
	function get_nameIndex() { return $this->nameIndex; }

	//
	function set_flags($flags) { $this->flags = $flags; }
	function get_flags() { return $this->flags; }

	//
	function set_options($options) { $this->options = $options; }
	function get_options() { return $this->options; }

	//
	function set_paramNames($paramNames) { $this->paramNames = $paramNames; }
	function get_paramNames() { return $this->paramNames; }

	//
	function set_methodInfo_data(){
		/* TODO */
		$this->buf = "";
		$this->buf .= write_u30(count($this->pTypes));
		$this->buf .= write_u30($this->returnType);

		foreach($this->pTypes as $p) $this->buf .= write_u30($p);

		$this->buf .= write_u30($this->nameIndex);

		$oiCount = count($this->options);
		$piCount = count($this->paramNames);

		$oiBuf = "";
		$piBuf = "";

		if($oiCount) {
			$this->flags |= HAS_OPTIONAL;
			$oiBuf .= write_u30(count($this->pType));

			foreach($this->options as $p) {
				$this->buf .= write_u30($p[0]);
				$this->buf .= chr($p[1]);
			}
		}
		if($piCount) {
			$this->flags |= HAS_PARAM_NAMES;

			foreach($this->paramNames as $pn) $this->buf .= write_u30($pn);
		}

		$this->buf .= chr($this->flags);
		$this->buf .= $oiBuf;
		$this->buf .= $piBuf;

		return $this->buf;
	}

	//
	function get_methodInfo_data(){
		/* TODO */
	}

	function get_buf(){
		return $this->set_methodInfo_data();
	}
	//
	function fetch_assoc() {
		/* TODO */
	}

	//
	function fetch_xml() {
		/* TODO */
	}
}


/**
 *
 */
class InstanceInfoEntry {

	var $buf = 0;

	var $nameIndex = 0;			// u30
	var $superNameIndex = 0;	// u30
	var $flags = 0;				// u8
	var $protectedNs = 0;		// u30
	//var $interfaceCount = 0;	// u30
	var $interfaces = array();
	var $iinit = 0;				// u30

	//var $traitCount = 0;		// u30
	var $traits = array();	//



	// the constructor
	function InstanceInfoEntry($nameIndex = 0, $superNameIndex = 0, $flags = 0, $protectedNs = 0, $interfaces = array(), $iinit = 0, $traits = array()){
		$this->nameIndex = $nameIndex;
		$this->superNameIndex = $superNameIndex;
		$this->flags = $flags;
		$this->protectedNs = $protectedNs;
		$this->interfaces = $interfaces;
		$this->iinit = $iinit;
	}

	//
	function set_nameIndex($nameIndex)	{ $this->nameIndex = $nameIndex; }
	function get_nameIndex() { return $this->nameIndex; }

	//
	function set_superNameIndex($superNameIndex) { $this->superNameIndex = $superNameIndex; }
	function get_superNameIndex() { return $this->superNameIndex; }

	//
	function set_flags($flags) { $this->flags = $flags; }
	function get_flags() { return $this->flags; }

	//
	function set_protectedNs($protectedNs) { $this->protectedNs = $protectedNs; }
	function get_protectedNs() { return $this->protectedNs; }

	//
	function set_interfaces($interfaces) { $this->interfaces = $interfaces; }
	function get_interfaces() { return $this->interfaces; }

	//
	function set_iinit($iinit) { $this->iinit = $iinit; }
	function get_iinit() { return $this->iinit; }

	//
	function set_traits($traits) { $this->traits = $traits; }
	function get_traits() { return $this->traits; }


	//
	function set_instanceInfo_data(){
		/* TODO */
		$this->buf = write_u30($this->nameIndex);
		$this->buf .= write_u30($this->superNameIndex);
		$this->buf .= chr($this->flags);

		if($this->flags & CONSTANT_ClassProtectedNs)
			$this->buf .= write_u30($this->protectedNs);

		$iCount = count($this->interfaces);
		$this->buf .= write_u30($iCount);


		if($iCount){
			foreach($this->interfaces as $i) $this->buf .= write_u30($i);
		}

		$this->buf .= write_u30($this->iinit);

		$tCount = count($this->traits);
		$this->buf .= write_u30($tCount);


		if($tCount){
			foreach($this->traits as $ti) $this->buf .= $ti->get_buf();
		}

		return $this->buf;
	}

	//
	function get_instanceInfo_data(){
		/* TODO */
	}

	//
	function fetch_assoc() {
		/* TODO */
	}

	//
	function fetch_xml() {
		/* TODO */
	}

	//
	function get_buf(){
		return $this->set_instanceInfo_data();
	}
}

/**
 * class and script info entry
 */
class CsInfoEntry {

	var $buf = "";

	var $initIndex = 0;	// u30
	// var $traitCount = 0;	// u30
	var $traits = array();

	function CsInfoEntry($initIndex = 0, $traits = array()){

		$this->initIndex = $initIndex;
		$this->traits = $traits;
	}

	//
	function set_initIndex($initIndex) { $this->initIndex = $initIndex; }
	function get_initIndex() { return $this->initIndex; }

	//
	function set_traits($traits) { $this->traits = $traits; }
	function get_traits() { $this->traits; }

	//
	function add_traitInfo($trait) {
		$this->traits[] = $trait;
	}

	//
	function set_csInfo_data(){
		$this->buf = write_u30($this->initIndex);

		$tCount = count($this->traits);
		$this->buf .= write_u30($tCount);

		if($tCount){
			foreach($this->traits as $ti) $this->buf .= $ti->get_buf();
		}

		return $this->buf;
	}

	//
	function get_csInfo_data(){
		/* TODO */
	}

	//
	function fetch_assoc() {
		/* TODO */
	}

	//
	function fetch_xml() {
		/* TODO */
	}

	//
	function get_buf(){
		return $this->set_csInfo_data();
	}
}


/**
 *
 */
class TraitInfoEntry {

	var $nameIndex = 0; // u30
	var $kind = 0;		// u8, higher 4 bit is flag, lower 4 type

	var $data = array();	  // items depends on kind
	//var $metadataCount = 0; // u30

	var $metadata = array();

	// the constructor
	function TraitInfoEntry($nameIndex = 0, $kind = 0, $data = array(), $metadata = array()) {
		$this->nameIndex = $nameIndex;
		$this->kind = $kind;
		$this->data = $data;
		$this->metadata = $metadata;
	}


	//
	function set_nameIndex($nameIndex) { $this->nameIndex = $nameIndex; }
	function get_nameIndex() { return $this->nameIndex; }

	//
	function set_kind($kind) { $this->kind = $kind; }
	function get_kind() { return $this->kind; }

	//
	function set_data($data) { $this->data = $data; }
	function get_data() { return $this->data; }

	//
	function set_metadata($metadata) { $this->metadata = $metadata; }
	function get_metadata() { return $this->metadata; }

	//
	function set_traitInfo_data(){

		$this->buf = write_u30($this->nameIndex);
		$this->buf .= chr($this->kind);

		$traitAttr = ($this->kind & 0xF0) ? true : false;
		$traitType = $this->kind & 0x0F;

		$this->buf .= write_u30($this->data[0]);
		$this->buf .= write_u30($this->data[1]);

		if($traitType == TRAIT_Slot || $traitType == TRAIT_Const){
			$this->buf .= write_u30($this->data[2]);
			$this->buf .= write_u30($this->data[3]);
			$this->buf .= chr($this->data[4]);
		}

		if($traitAttr & ATTR_Metadata){
			$this->buf .= write_u30(count($this->metadata));

			foreach($this->metadata as $md) $this->buf .= write_u30($md);
		}

		return $this->buf;
	}

	//
	function get_traitInfo_data(){
		/* TODO */
	}

	//
	function fetch_assoc() {
		/* TODO */
	}

	//
	function fetch_xml() {
		/* TODO */
	}

	//
	function get_buf(){
		return $this->set_traitInfo_data();
	}
}


/**
 *
 */
class MethodBodyInfoEntry {

	var $buf = "";

	var $method = 0;		 		// u30
	var $maxStack = 0;		 		// u30
	var $localCount = 0;	 		// u30
	var $initScopeDepth = 0; 		// u30
	var $maxScopeDepth = 0;	 		// u30

	//var $codeLength = 0;			// u30
	var $rawCode = array();			// contains raw opcodes (e.g. read from buf)
	var $code = array();	 		// u8[codeLength] store "asm syntax" opcodes

	//var $exceptionCount = 0;  	// u30
	var $exceptions = array();	// exception[exception_count]
	//var $traitCount = 0;		  	// u30
	var $traits = array();			//


	// the constructor
	function MethodBodyInfoEntry($method = 0,
								$maxStack = 0, $localCount = 0, $initScopeDepth = 0, $maxScopeDepth = 0,
								$rawCode = array(),
								$exceptions = array(), $traits = array()) {

		$this->method = $method;
		$this->maxStack = $maxStack;
		$this->localCount = $localCount;
		$this->initScopeDepth = $initScopeDepth;
		$this->maxScopeDepth = $maxScopeDepth;
		$this->rawCode = $rawCode;
		$this->exceptions = $exceptions;
		$this->traits = $traits;
	}


	//
	function set_method($method) { $this->method = $method; }
	function get_method() { $this->method; }

	//
	function set_maxStack($maxStack) { $this->maxStack = $maxStack; }
	function get_maxStack() { return $this->maxStack; }

	//
	function set_localCount($localCount) { $this->localCount = $localCount; }
	function get_localCount() { return $this->localCount; }

	//
	function set_initScopeDepth($initScopeDepth) { $this->initScopeDepth = $initScopeDepth; }
	function get_initScopeDepth() { return $this->initScopeDepth; }

	//
	function set_maxScopeDepth($maxScopeDepth) { $this->maxScopeDepth = $maxScopeDepth; }
	function get_maxScopeDepth() { return $this->maxScopeDepth; }

	//
	function set_rawCode($rawCode) { $this->rawCode = $rawCode; }
	function get_rawCode() { return $this->rawCode; }

	function set_rawCode_from_buf($buf) {
		$this->code = array();
		foreach($buf as $b) $this->code[] = ui8dec($b);
	}

	function set_rawCode_from_base64($b64Str){
		$buf = base64_decode($b64Str);
		$this->set_rawCode_from_buf($buf);
	}

	//
	function set_code($code) { $this->code = $code; }
	function get_code() { return $this->code; }

	//
	function set_exceptions($exceptions) { $this->exceptions = $exceptions; }
	function get_exceptions() { return $this->exceptions; }

	//
	function set_traits($traits) { $this->traits = $traits; }
	function get_traits() { return $this->traits; }

	function set_methodBody_data(){

		$this->buf = write_u30($this->method);
		$this->buf .= write_u30($this->maxStack);
		$this->buf .= write_u30($this->localCount);
		$this->buf .= write_u30($this->initScopeDepth);
		$this->buf .= write_u30($this->maxScopeDepth);

		$cCount = count($this->rawCode);
		if($cCount){
			$this->buf .= write_u30($cCount);

			foreach($this->rawCode as $c) $this->buf .= chr($c);
		}
		else {
			/* TODO */
			//assemble();
		}

		$eCount = count($this->exceptions);
		$this->buf .= write_u30($eCount);

		if($eCount){
			foreach($this->exceptions as $e) $this->buf .= $e->get_buf();
		}

		$tCount = count($this->traits);
		$this->buf .= write_u30($tCount);

		if($tCount){
			foreach($this->traits as $ti) $this->buf .= $ti->get_buf();
		}

		return $this->buf;
	}

	//
	function get_methodBody_data(){
		/* TODO */
	}

	//
	function fetch_assoc() {
		/* TODO */
	}

	//
	function fetch_xml() {
		/* TODO */
	}

	//
	function get_buf(){
		return $this->set_methodBody_data();
	}
}

class ExceptionInfoEntry {

	var $from = 0;	 	 // u30
	var $to = 0;	 	 // u30
	var $target = 0;	 // u30
	var $excType = 0;	 // u30
	var $varName = 0;	 // u30

	// the constructor
	function ExceptionInforEntry($from = 0, $to = 0, $target = 0, $excType = 0, $varName = 0){
		$this->from = $from;
		$this->to = $to;
		$this->target = $target;
		$this->excType = $excType;
		$this->varName = $varName;
	}

	//
	function set_from($from) { $this->from = $from; }
	function get_from() { return $this->from; }

	//
	function set_to($to) { $this->to = $to; }
	function get_to() { return $this->to; }

	//
	function set_target($target) { $this->target = $target; }
	function get_target() { return $this->target; }

	//
	function set_excType($excType) { $this->excType = $excType; }
	function get_excType() { return $this->excType; }

	//
	function set_varName($varName) { $this->varName = $varName; }
	function get_varName() { return $this->varName; }

	//
	function set_exception_data(){
		$this->buf = wite_u30($this->from);
		$this->buf .=wite_u30($this->to);
		$this->buf .= wite_u30($this->target);
		$this->buf .= wite_u30($this->excType);
		$this->buf .= wite_u30($this->varName);

		return $this->buf;
	}

	//
	function get_exception_data(){
		/* TODO */
	}

	//
	function fetch_assoc() {
		/* TODO */
	}

	//
	function fetch_xml() {
		/* TODO */
	}

	//
	function get_buf(){
		return $this->set_exception_data();
	}
}

// BULK CLASSES

/**
 * create a bulk as3 class to link bitmap asset
 */
class DummyAs3BitmapClass {

	var $className;
	var $bitmapID;
	var $doABC2;

	function DummyAs3BitmapClass ($className = "Mypng", $bitmapID = 1){
		$this->className = $className;
		$this->bitmapID = $bitmapID;

		$this->doABC2 = new MKAbcContainer();
		$this->build_bulk_class();
	}

	//
	function build_bulk_class(){

		// cp string
		$this->doABC2->add_constantString(""); // stands for "*" ("any")
		$this->doABC2->add_constantString("Number");
		$this->doABC2->add_constantString($this->className);
		$this->doABC2->add_constantString("flash.display");
		$this->doABC2->add_constantString("BitmapData");
		$this->doABC2->add_constantString("Object");

		// cp namespace
		$this->doABC2->add_constantNamespace(array(CONSTANT_PackageNamespace, 1));
		$this->doABC2->add_constantNamespace(array(CONSTANT_PackageNamespace, 4));
		$this->doABC2->add_constantNamespace(array(CONSTANT_ProtectedNamespace, 3));

		// cp multiname
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(1, 2)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(1, 3)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(2, 5)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(1, 6)));


		// method
		$mi = new MethodInfoEntry();
		$this->doABC2->add_methodInfo($mi);

		$mi = new MethodInfoEntry(0, array(1, 1));
		$this->doABC2->add_methodInfo($mi);

		$mi = new MethodInfoEntry();
		$this->doABC2->add_methodInfo($mi);

		// instance and class
		$ii = new InstanceInfoEntry(2, 3, CONSTANT_ClassProtectedNs, 3, array(), 1);
		$this->doABC2->add_instanceInfo($ii);

		$cs = new CsInfoEntry();
		$this->doABC2->add_classInfo($cs);

		// script
		$cs = new CsInfoEntry(2);
		$trait = new TraitInfoEntry(2, TRAIT_Class, array(1, 0));
		$cs->add_traitInfo($trait);
		$this->doABC2->add_scriptInfo($cs);

		// method body
		$mb = new MethodBodyInfoEntry(0, 1, 1, 4, 5);
		$mb->set_rawCode(array(0xD0, 0x30, 0x47));
		$this->doABC2->add_methodBodyInfo($mb);

		$mb = new MethodBodyInfoEntry(1, 3, 3, 5, 6);
		$mb->set_rawCode(array(0xD0, 0x30, 0xD0, 0xD1, 0xD2, 0x49, 0x02, 0x47));
		$this->doABC2->add_methodBodyInfo($mb);

		$mb = new MethodBodyInfoEntry(2, 2, 1, 1, 4);
		$mb->set_rawCode(array(0xd0, 0x30, 0x65, 0x00, 0x60, 0x04, 0x30, 0x60, 0x03, 0x30, 0x60, 0x03, 0x58, 0x00, 0x1d, 0x1d, 0x68, 0x02, 0x47));
		$this->doABC2->add_methodBodyInfo($mb);
	}

	//
	function update_tagData() {
		return $this->doABC2->update_tagData();
	}
}


class DummyAs3DisplayObjectClass {

	var $className;
	var $doID;
	var $doABC2;

	function DummyAs3DisplayObjectClass ($className = "MySymbol", $doID = 1){
		$this->className = $className;
		$this->doID = $doID;

		$this->doABC2 = new MKAbcContainer();
		$this->build_bulk_class();
	}

	//
	function build_bulk_class(){

		// cp int - no cp int
		// cp uint - no cp uint
		// cp double - no cp double

		// cp string
		$cps = array("", $this->className, "flash.display", "MovieClip", "Object", "flash.events",
					"EventDispatcher", "DisplayObject", "InteractiveObject", "DisplayObjectContainer", "Sprite");

		foreach($cps as $c) $this->doABC2->add_constantString($c);

		// cp namespace
		$this->doABC2->add_constantNamespace(array(CONSTANT_PackageNamespace, 1));
		$this->doABC2->add_constantNamespace(array(CONSTANT_PackageNamespace, 3));
		$this->doABC2->add_constantNamespace(array(CONSTANT_ProtectedNamespace, 2));
		$this->doABC2->add_constantNamespace(array(CONSTANT_PackageNamespace, 6));

		// namespace set - no namespace set

		// cp multiname
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(1, 2)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(2, 4)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(1, 5)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(4, 7)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(2, 8)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(2, 9)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(2, 10)));
		$this->doABC2->add_constantMultiname(array(CONSTANT_QName, array(2, 11)));


		// method
		$mi = new MethodInfoEntry();
		$this->doABC2->add_methodInfo($mi);

		$mi = new MethodInfoEntry();
		$this->doABC2->add_methodInfo($mi);

		$mi = new MethodInfoEntry();
		$this->doABC2->add_methodInfo($mi);

		// metadata - no metadata

		// instance and class
		$ii = new InstanceInfoEntry(1, 2, CONSTANT_ClassProtectedNs, 3, array(), 1);
		$this->doABC2->add_instanceInfo($ii);

		$cs = new CsInfoEntry();
		$this->doABC2->add_classInfo($cs);

		// script
		$cs = new CsInfoEntry(2);
		$trait = new TraitInfoEntry(1, TRAIT_Class, array(1, 0));
		$cs->add_traitInfo($trait);
		$this->doABC2->add_scriptInfo($cs);

		// method body
		$mb = new MethodBodyInfoEntry(0, 1, 1, 9, 10);
		$mb->set_rawCode(array(0xD0, 0x30, 0x47));
		$this->doABC2->add_methodBodyInfo($mb);

		$mb = new MethodBodyInfoEntry(1, 1, 1, 10, 11);
		$mb->set_rawCode(array(0xD0, 0x30, 0xD0, 0x49, 0x00, 0x47));
		$this->doABC2->add_methodBodyInfo($mb);

		$mb = new MethodBodyInfoEntry(2, 2, 1, 1, 9);
		$mb->set_rawCode(array( 0XD0, 0X30, 0X65, 0X00, 0X60, 0X03, 0X30, 0X60,
								0X04, 0X30, 0X60, 0X05, 0X30, 0X60, 0X06, 0X30,
								0X60, 0X07, 0X30, 0X60, 0X08, 0X30, 0X60, 0X02,
								0X30, 0X60, 0X02, 0X58, 0X00, 0X1D, 0X1D, 0X1D,
								0X1D, 0X1D, 0X1D, 0X1D, 0X68, 0X01, 0X47));

		$this->doABC2->add_methodBodyInfo($mb);
	}

	//
	function update_tagData() {
		return $this->doABC2->update_tagData();
	}
}

// -------------------- end of mk_cs_swf9_bulk ----------------------
?>
